#!/usr/bin/python
# -*- coding: utf-8 -*-

import simplejson
import MuConnection
import time
from StringIO import StringIO
import logging
log = logging.getLogger('MuPython.MuNetworkConfiguration')

""" MuNetworkConfiguration contains all the necisary classes and methods for altering the network
configuration of the Mu Test Suite Appliance

example URLs for the Mu NetConfig API
-------------------------------------------------------------------------------
https://MyMu/restlet/netconfig/                      ----> gets all
https://MyMu/restlet/netconfig/hosts/                ----> gets all hosts
https://MyMu/restlet/netconfig/routes/               ----> gets all routes
https://MyMu/restlet/netconfig/interfaces/           ----> gets all interfaces
https://MyMu/restlet/netconfig/hosts/myHostName1     ----> gets a host
https://MyMu/restlet/netconfig/interfaces/a2.101     ----> gets an interface
https://MyMu/restlet/netconfig/routes/192.168.100.0  ----> gets a route
-------------------------------------------------------------------------------

If request is good you get a jason object back.
If request is bad and an URL error or jason object containing an error is returned:
{
"ERROR_DESCRIPTION": "Get failed, 192.168.110.0 does not exist.",
"ERROR_NAME": "NetworkConfigError"
}

Classes contained:
MuNetworkConfig - instantiated by passing in a MuConnection and is used to mannage the Mu 
network configuration.

interface - used to represent a Mu Interfaces

host - used to represent a host entry in the Mu host table. This object can contain sshChannels, 
telnetChannels, or consoleChannels.

route - used to represent a route for a mu interface.

sshChannel - used to represent a ssh channel for a Host. This object can contain a list of 
commands.

telnetChannel - used to represent a telnet channel for a Host. This object can contain a list 
of commands

consoleChannel - used to represent a console channel for a Host. This object can contain a list 
of commands

command - used to represent a setup command for a channel. normaly used to ensure correct 
login and privledge level is reached

"""


class MuNetworkConfig:

    """ MuNetworkConfig: This class is instantiated by passing in a 
    MuConnection and is used to mannage the Mu network configurations.
    -------------------------------------------------------------------------
    example JSON config data
    [{'interfaces': [{'display_name': 'A1','mac': '00:04:23:c8:eb:04','name': 'a1','up': True,'v4_addrs': ['192.168.100.201','192.168.100.202','192.168.100.203'],'v4_dhcp': False,'v4_dhcp_status': 'DISABLED','v4_mask': '24','v6_global_addrs': ['2003:0:0:0:0:0:0:10','2003:0:0:0:0:0:0:11','2003:0:0:0:0:0:0:12','2003:0:0:0:0:0:0:13'],'v6_global_mask': '64','v6_local_addr': '','vlan': ''},
    {'display_name': 'A2','mac': '00:04:23:c8:ed:78','name': 'a2','up': True,'v4_addrs': ['192.168.100.210','192.168.100.211'],'v4_dhcp': False,'v4_dhcp_status': 'DISABLED','v4_mask': '24','v6_global_addrs': ['2003:0:0:0:0:0:0:20','2003:0:0:0:0:0:0:21'],'v6_global_mask': '64','v6_local_addr': '','vlan': ''},
    {'display_name': 'Mgmt','mac': '00:30:48:8a:21:88','name': 'eth0','up': True,'v4_addrs': ['192.168.1.254'],'v4_dhcp': False,'v4_dhcp_status': 'DISABLED','v4_mask': '24','v6_global_addrs': [],'v6_global_mask': '','v6_local_addr': 'fe80:0:0:0:230:48ff:fe8a:2188','vlan': ''},
    {'display_name': 'Aux','mac': '00:30:48:8a:21:89','name': 'eth1','up': True,'v4_addrs': ['192.168.22.1'],'v4_dhcp': False,'v4_dhcp_status': 'DISABLED','v4_mask': '24','v6_global_addrs': [],'v6_global_mask': '','v6_local_addr': '','vlan': ''},
    {'display_name': 'A2.101','mac': '00:04:23:c8:ed:78','name': 'a2.101','up': True,'v4_addrs': [],'v4_dhcp': False,'v4_dhcp_status': 'DISABLED','v4_mask': '','v6_global_addrs': [],'v6_global_mask': '','v6_local_addr': 'fe80:0:0:0:204:23ff:fec8:ed78','vlan': 101},
    {'display_name': 'A2.102','mac': '00:04:23:c8:ed:78','name': 'a2.102','up': True,'v4_addrs': [],'v4_dhcp': False,'v4_dhcp_status': 'DISABLED','v4_mask': '','v6_global_addrs': [],'v6_global_mask': '','v6_local_addr': 'fe80:0:0:0:204:23ff:fec8:ed78','vlan': 102}]},
    {'routes': [{'default': False,'direct': True,'dst': '192.168.100.0','dst_pfx_len': 24,'gateway': '0.0.0.0','interface': 'a1','interface_display_name': 'A1','metric': 0,'readonly': True},
    {'default': False,'direct': True,'dst': '192.168.22.0','dst_pfx_len': 24,'gateway': '0.0.0.0','interface': 'eth1','interface_display_name': 'Aux','metric': 0,'readonly': True},
    {'default': False,'direct': True,'dst': '192.168.1.0','dst_pfx_len': 24,'gateway': '0.0.0.0','interface': 'eth0','interface_display_name': 'Mgmt','metric': 0,'readonly': True},
    {'default': False,'direct': False,'dst': '192.168.1.0','dst_pfx_len': 24,'gateway': '192.168.100.1','interface': 'a1','interface_display_name': 'A1','metric': 0,'readonly': False},
    {'default': False,'direct': True,'dst': '169.254.0.0','dst_pfx_len': 16,'gateway': '0.0.0.0','interface': 'eth1','interface_display_name': 'Aux','metric': 0,'readonly': True}]},
    {'hosts': [{'mac': '','name': 'HostName2','notes': '','v4_addr': '192.168.1.199','v6_global_addr': '','v6_local_addr': ''},
    {'mac': '','name': 'HostName','notes': '','v4_addr': '192.168.1.253','v6_global_addr': '','v6_local_addr': ''}]}]
    -------------------------------------------------------------------------
    
    Arguments: 
    MuConnection - The connection class for maintaining a SSL session to 
    the Mu Test Suite
    
    Globals:
    VERBOSE - turn on debug printing
    __MuJasonConfig - JSON config from Mu
    muConnection - connection to the Mu Test Server
    
    TODO:
    Need to implement a logging method
    """

    VERBOSE = False
    __MuJasonConfig = None
    muConnection = None

    def __init__(self, connection):
        """ set up the TestAPI with the passed in MuConnection """

        self.muConnection = connection

    def downloadNetworkConfigObject(self, url=""):
        """ download a root network config JSON object from the Mu test 
        server
        Example URL: https://$MU_IP/restlet/netconfig/
        
        Arguments:
        url - the url of the desired netconfig object to be retrieved

        Returns:
        JSON formated list
        """

        load = False
        if url == "":
            url = self.muConnection.TOP_LEVEL_URL + \
                "/restlet/netconfig/"
            load = True
        elif url.endswith("/restlet/netconfig/"):
            load = True
        else:
            return {"ERROR": "Invalid url-> " + url}
        responseBuffer = self.muConnection.getRequestBuffer(url)
        jsonConfigObject = simplejson.load(responseBuffer)
        if load:
            self.__MuJasonConfig = jsonConfigObject
        return jsonConfigObject

    def getNetworkConfigObjectData(self, url, isJasonResponse=False):
        """ used to get specific JSON data from the Mu. Uses the GET method
        
        Arguments:
        url - the url of the desired netconfig object to be retrieved
        isJasonResponse - used to indicate that the returned data should 
        be processed as a JSON object
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        responseData = self.muConnection.get(url, isJasonResponse)
        return responseData

    def addNetworkConfigObject(self, url, jsonDataToSend, 
                               isJsonResponse=False):
        """ used to add specific JSON data to the Mu. Uses the POST method
        
        Arguments:
        url - the url of the desired netconfig object to be retrieved
        jsonDataToSend - JSON formated objet to send to Mu
        isJasonResponse - used to indicate that the returned data should 
        be processed as a JSON object
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        responseData = self.muConnection.post(url, jsonDataToSend,
                "application/json; charset=utf-8", isJsonResponse)
        return responseData

    def modifyNetworkConfigObject(self, url, jsonDataToSend,
                                  isJsonResponse=False):
        """ used to modify existing JSON data on the Mu. Uses the PUT method

        Arguments:
        url - the url of the desired netconfig object to be retrieved
        jsonDataToSend - JSON formated objet to update on the Mu
        isJasonResponse - used to indicate that the returned data should 
        be processed as a JSON object
        
        Returns:
        MuConnection.MuResponseObject
        """

        responseData = self.muConnection.put(url, jsonDataToSend,
                "application/json; charset=utf-8", isJsonResponse)
        return responseData

    def deleteNetworkConfigObject(self, url, isJasonResponse=False):
        """ used to delete existing JSON data on the Mu. Uses the 
        DELETE method

        Arguments:
        url - the url of the desired netconfig object to be retrieved
        isJasonResponse - used to indicate that the returned data 
        should be processed as a JSON object
        
        Returns:
        MuConnection.MuResponseObject
        """

        responseData = self.muConnection.delete(url, isJasonResponse)
        return responseData

    def addHost(self, hostToAdd):
        """ used to add a network host to the Mu server
        Example URL: https://$MU_IP/restlet/netconfig/hosts/
        
        Arguments:
        hostToAdd - the MuNetworkConfiguration.host object to add to the Mu 
        server network configuration
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        jsonString = simplejson.dumps(hostToAdd.getHostData())
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/hosts/'
        log.debug("URL: %s", url)
        log.debug("JSON String: %s", jsonString)
        response = self.addNetworkConfigObject(url, jsonString, True)
        log.debug("Response: %s", response)
        return response

    def deleteHost(self, hostToDelete):
        """ used to delete a network host on the Mu server
        Example URL: https://$MU_IP/restlet/netconfig/hosts/myHostnameToDelete
        
        Arguments:
        hostToDelete - the MuNetworkConfiguration.host object to 
        delete on the Mu server network configuration
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/hosts/' + hostToDelete.getName()
        response = self.deleteNetworkConfigObject(url, True)
        log.debug(response)
        return response

    def modifyHost(self, hostToModify):
        """ used to modify a network host on the Mu server
        Example URL: https://$MU_IP/restlet/netconfig/hosts/myHostnameToModify
        
        Arguments:
        hostToModify - the MuNetworkConfiguration.host object used to 
        base modifications on the Mu server network configuration
        
        Returns:
        MuConnection.MuResponseObject
        """

        jsonString = simplejson.dumps(hostToModify.getHostData())
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/hosts/' + hostToModify.getName()
        response = self.modifyNetworkConfigObject(url, jsonString)
        if response.isCompleted() == False:
            result = False
        else:
            result = True
        log.debug(response)
        return response

    def isHostPresent(self, hostName=""):
        """ used to check for the presense of a host on the Mu server
        Example URL: https://$MU_IP/restlet/netconfig/hosts/myHostnameToCehck
        
        Arguments:
        hostName - the hostname to search for on the Mu server 
        
        Returns:
        boolean
        """
        
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/hosts/' + hostName
        response = self.getNetworkConfigObjectData(url, True)
        if response.isCompleted() == False:
            result = False
        elif response.hasError() == True:
            result = False
        else:
            result = True
        log.debug(response)
        return result

    def getHost(self, hostName=""):
        """ used to get a network host on the Mu server
        Example URL: https://$MU_IP/restlet/netconfig/hosts/myHostnameToGet
        
        Arguments:
        hostName - the hostname to get from the Mu server
        
        Returns:
        MuNetworkConfiguration.host object
        """
        
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/hosts/' + hostName
        response = self.getNetworkConfigObjectData(url, True)
        if response.isCompleted():
            hostData = host(response.getJsonObject())
        else:
            hostData = None
        log.debug(response)
        return hostData

    def getHostList(self):
        """ used to get a JSON list of all hosts on the Mu server
        
        Arguments:
        none
        
        Returns:
        JSON formated object list of all hosts on the Mu serer
        """

        self.downloadNetworkConfigObject()
        return (self.__MuJasonConfig)[2]['hosts']

    def setHostList(self, jsonFormatedList):
        """ not realy used and will probably go away """

        (self.__MuJasonConfig)[2]['hosts'] = jsonFormatedList

    def getInterfaceList(self):
        """ used to get a JSON list of all interfaces on the Mu server
        
        Arguments:
        none
        
        Returns:
        JSON formated object list of all interfaces on the Mu serer
"""

        self.downloadNetworkConfigObject("")
        return (self.__MuJasonConfig)[0]['interfaces']

    def setInterfaces(self, jsonFormatedList):
        """ not realy used and will probably go away """

        (self.__MuJasonConfig)[0]['interfaces'] = jsonFormatedList

    def addInterface(self, interfaceToAdd):
        """ used to add a network interface to the Mu server. You can only 
        add a vlan nterface. 
        When adding a vlan only name and vlan are added first, then 
        a modify with everything else is done.
        
        Arguments:
        interfaceToAdd - the MuNetworkConfiguration.interface object 
        to add to the Mu server 
        
        Returns:
        MuConnection.MuResponseObject
        """

        tmpVal = interfaceToAdd.getName()
        tmpVal = tmpVal.split(".")
        if len(tmpVal) == 2:
            name = tmpVal[0]
            vlan = tmpVal[1]
            dualTag = False
        elif len(tmpVal) == 3:
            name = tmpVal[0] + "." + tmpVal[1]
            vlan = tmpVal[2]
            dualTag = True
        else:
            log.error("ERROR: UNKNOWN VLAN FORMAT FOR INTERFACE")
        response = self.addVlan(name, vlan, dualTag)
        if response.isCompleted() == False or response.hasError():
            return response
        else:
            response = self.modifyInterface(interfaceToAdd)
        return response

    def addVlan(self, interfaceName, vlan, dualTag=False):
        """ used to add a vlan interface to the Mu server. When adding 
        a vlan only name and vlan are added first. There is a 5 sec 
        delay added to this command to ensure completion of interface 
        before command is completed.
        
        Arguments:
        interfaceName - string of the parent interface to add sub vlan 
        interface. a1 --> a1.101, a1.101 --> a1.101.1001
        vlan - the string containing the vlan tag of the new sub inerface.
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        tmpJsonData = {"vlan": vlan, "name": interfaceName}
        jsonString = simplejson.dumps(tmpJsonData)
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/interfaces/'
        response = self.addNetworkConfigObject(url, jsonString, True)
        log.debug(response)
        time.sleep(5)  # delay used to ensure vlan interface is created before modification is attempted
        return response

    def deleteInterface(self, interfaceToDelete):
        """ used to delete a interface on the Mu server. Only vlan interfaces 
        can be deleted. All routes for the interace are also deleted 
        
        Arguments:
        interfaceToDelete - the MuNetworkConfiguration.interface object 
        to delete on the Mu server 
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/interfaces/' + interfaceToDelete.getName()
        response = self.deleteNetworkConfigObject(url, True)
        if response.isCompleted() == False:
            result = False
        else:
            result = True
        log.debug(response)
        return response

    def modifyInterface(self, interfaceToModify):
        """ used to mofify an existing interface on the Mu server.
        
        Arguments:
        interfaceToModify - the MuNetworkConfiguration.interface object 
        to modify on the Mu server 
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        jsonString = simplejson.dumps(interfaceToModify.getInterfaceData())
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/interfaces/' + interfaceToModify.getName()
        log.debug("Modify Interface URL: %s", url)
        log.debug("Modify Interface JSON String : %s", jsonString)
        response = self.modifyNetworkConfigObject(url, jsonString, True)
        if response.isCompleted() == False:
            result = False
        else:
            result = True
        log.debug(response)
        return response

    def isInterfacePresent(self, interfaceName):
        """ used to mofify an existing interface on the Mu server.
        
        Arguments:
        interfaceName - the string containing the interface name on the 
        Mu to check for  
        
        Returns:
        boolean
        """
        
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/interfaces/' + interfaceName
        response = self.getNetworkConfigObjectData(url, True)
        if response.isCompleted() == False:
            result = False
        else:
            result = True
        log.debug(response)
        return result

    def getInterface(self, interfaceName):
        """ used to mofify an existing interface on the Mu server.
        
        Arguments:
        interfaceName - the string containing the interface name on 
        the Mu to get 
        
        Returns:
        MuNetworkConfiguration.interface
        """
        
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/interfaces/' + interfaceName
        response = self.getNetworkConfigObjectData(url, True)
        if response.isCompleted():
            inerfaceData = interface(response.getJsonObject())
        else:
            inerfaceData = None
        log.debug(response)
        return inerfaceData

    def getRouteList(self):
        """ used to get a JSON list of all routes on the Mu server
        
        Arguments:
        none
        
        Returns:
        JSON formated object list of all routes on the Mu serer
        """
        
        downloadNetworkConfigObject("")
        return (self.__MuJasonConfig)[1]['routes']

    def setRouteList(self, jsonFormatedList):
        """ not realy used and will probably go away """

        (self.__MuJasonConfig)[1]['routes'] = jsonFormatedList

    def addRoute(self, routeToAdd):
        """ used to add a route to the Mu server.
        
        Arguments:
        routeToAdd - the MuNetworkConfiguration.route object to add to 
        the Mu server.
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        jsonString = simplejson.dumps(routeToAdd.getRouteData())
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/routes/'
        response = self.addNetworkConfigObject(url, jsonString, True)
        if response.isCompleted() == False:
            result = False
        else:
            result = True
        log.debug(response)
        return response

    def modifyRoute(self, routeToModify):
        """ used to modify a route to the Mu server.
        
        Arguments:
        routeToAdd - the MuNetworkConfiguration.route object to modify 
        on the Mu server.
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        jsonString = simplejson.dumps(routeToModify.getRouteData())
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/routes/' + routeToModify.getDst()
        response = self.modifyNetworkConfigObject(url, jsonString, True)
        if response.isCompleted() == False:
            result = False
        else:
            result = True
        log.debug(response)
        return response

    def deleteRoute(self, routeToDelete):
        """ used to delete a route to the Mu server.
        
        Arguments:
        routeToAdd - the MuNetworkConfiguration.route object to delete 
        on the Mu server.
        
        Returns:
        MuConnection.MuResponseObject
        """
        
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/routes/' + routeToDelete.getDst()
        response = self.deleteNetworkConfigObject(url, True)
        if response.isCompleted() == False:
            result = False
        else:
            result = True
        log.debug(response)
        return response

    def isRoutePresent(self, routeDst, routeTnterface=""):
        """ used to check if a route is present on the Mu server. CAUTION: 
        if multiple routes exists for the same network (ie the same network 
        route exisits on a1, b1, a2 etc.), then it is possible to get a 
        false positive. It may be more efective to get all routs and parse 
        them by interface
        
        Arguments:
        routeDst - the the string representing the host or network 
        destination of the route. 
        routeTnterface - TODO: string to verrify source of route is on 
        the correct mu interface
        
        Returns:
        MuConnection.MuResponseObject
        
        TODO: change this method to get all routes and pares for exact match.
        """

        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/routes/' + routeDst
        response = self.getNetworkConfigObjectData(url, True)
        if response.isCompleted() == False:
            result = False
        else:
            result = True
        log.debug(response)
        return result

    def getRoute(self, routeDst, routeInterface=""):
        """ used to get a route from the Mu server. CAUTION: if multiple 
        routes exists for the same network (ie the same network route 
        exisits on a1, b1, a2 etc.), then it is possible to get a route 
        back that is from the incorrect interface.  It may be more efective 
        to get all routs and parse them by interface.
        
        Arguments:
        routeDst - the the string representing the host or network 
        destination of the route. 
        routeTnterface - TODO: string to verrify source of route is on the 
        correct mu interface
        
        Returns:
        MuConnection.MuResponseObject
        
        TODO: change this method to get all routes and pares for exact match.
        """
        
        url = self.muConnection.TOP_LEVEL_URL + \
            '/restlet/netconfig/routes/' + routeDst
        response = self.getNetworkConfigObjectData(url, True)
        if response.isCompleted():
            routeData = route(response.getJsonObject())
        else:
            routeData = None
        log.debug(response)
        return routeData

    def getMuJsonConfig(self):
        """ get network configuration from the Mu server """

        downloadNetworkConfigObject("")
        return self.__MuJasonConfig


class interface:
    """ interface: This class represents all elements associated with a 
    Mu interface
    
    -------------------------------------------------------------------------
    example JSON config data
    {'display_name': '', 'mac': '00:00:00:00:00:00', 'name': '', 'up': True, 'v4_addrs': [], 
    'v4_dhcp': False, 'v4_dhcp_status': 'DISABLED', 'v4_mask': '', 'v6_global_addrs': [], 
    'v6_global_mask': '', 'v6_local_addr': '', 'vlan': ''}
    -------------------------------------------------------------------------
    
    Arguments: 
    jsonData - The JSON formated data used to populate the object
    
    Globals:
    """
    
    def __init__(self, jsonData=None):
        if jsonData == None:
            return
        self.loadFromJsonData(jsonData)
    
    __jsonData = {
        "display_name": "",
        "mac": '00:00:00:00:00:00',
        "name": "",
        "up": True,
        "v4_addrs": [],
        "v4_dhcp": False,
        "v4_dhcp_status": 'DISABLED',
        "v4_mask": "",
        "v6_global_addrs": [],
        "v6_global_mask": "",
        "v6_local_addr": "",
        "vlan": "",
        }

    def __str__(self):
        return simplejson.dumps(self.__jsonData)

    def loadFromJsonData(self, jsonData):
        self.__jsonData = jsonData

    def getInterfaceData(self):
        return self.__jsonData

    def getData(self, key):
        return (self.__jsonData)[key]

    def getDisplay_name(self):
        return self.getData("display_name")

    def getMac(self):
        return self.getData("mac")

    def getName(self):
        return self.getData("name")

    def getUp(self):
        return self.getData("up")

    def getV4_addrs(self):
        return self.getData("v4_addrs")['begin']

    def getV4_dhcp(self):
        return self.getData("v4_dhcp")

    def getV4_dhcp_status(self):
        return self.getData("v4_dhcp_status")

    def getV4_mask(self):
        return self.getData("v4_mask")

    def getV6_global_addrs(self):
        return self.getData("v6_global_addrs")

    def getV6_global_mask(self):
        return self.getData("v6_global_mask")

    def getV6_local_addr(self):
        return self.getData("v6_local_addr")

    def getVlan(self):
        return self.getData("vlan")

    def setData(self, key, data):
        (self.__jsonData)[key] = data

    def setMac(self, data):
        self.setData("mac", data)

    def setName(self, data):
        self.setData("name", data.lower())
        self.setData("display_name", data.upper())

    def setUp(self, data):
        self.setData("up", data)

    def setV4_addr_count(self, data):
        self.setData("v4_addr_count", data )

    def setV4_addrs(self, data):
        self.setData("v4_addrs", { "begin" : data })

    def setV4_dhcp(self, data):
        self.setData("v4_dhcp", data)

    def setV4_dhcp_status(self, data):
        self.setData("v4_dhcp_status", data)

    def setV4_mask(self, data):
        self.setData("v4_mask", data)

    def setV6_global_addrs(self, data):
        self.setData("v6_global_addrs", data)

    def setV6_global_mask(self, data):
        self.setData("v6_global_mask", data)

    def setV6_local_addr(self, data):
        self.setData("v6_local_addr", data)

    def setVlan(self, data):
        self.setData("vlan", data)


class host:
    """ host: This class represents all elements associated with a Mu host 
    object
    
    -------------------------------------------------------------------------
    example JSON config data
    {'mac': '', 'name': 'VoIP-Server', 'notes': '', 'v4_addr': '192.168.100.51', 
    'v6_global_addr': '', 'v6_local_addr': '', 'ssh_channel': {'commands': [], 'password': 'admin', 
    'prompt': '[#$>]', 'tcp_port': 22, 'username': 'admin'}}
    ------------------------------------------------------------------------
    
    Arguments: 
    jsonData - The JSON formated data used to populate the object
    
    Globals:
    """
    
    def __init__(self, jsonData=None):
        if jsonData == None:
            return
        self.loadFromJsonData(jsonData)
    
    __jsonData = {"mac": "", "name": 'VoIP-Server', 'notes': "",
                  'v4_addr': '192.168.100.51', 'v6_global_addr': "",
                  "v6_local_addr": ""}

    def __str__(self):
        return simplejson.dumps(self.__jsonData)

    def loadFromJsonData(self, jsonData):
        self.__jsonData = jsonData

    def getHostData(self):
        return self.__jsonData

    def getData(self, key):
        try:
            return (self.__jsonData)[key]
        except KeyError:
            return ""

    def getMac(self):
        return self.getData("mac")

    def getName(self):
        return self.getData("name")

    def getNotes(self):
        return self.getData('notes')

    def getTelnet_channel(self):
        return self.getData('telnet_channel')

    def getSsh_channel(self):
        return self.getData('ssh_channel')

    def getV4_addr(self):
        return self.getData('v4_addr')

    def getV6_global_addr(self):
        return self.getData('v6_global_addr')

    def getV6_local_addr(self):
        return self.getData("v6_local_addr")

    def getConsole_channel(self):
        return self.getData('console_channel')

    def setData(self, key, data):
        (self.__jsonData)[key] = data

    def setMac(self, data):
        self.setData("mac", data)

    def setName(self, data):
        self.setData("name", data)

    def setNotes(self, data):
        self.setData('notes', data)

    def setTelnet_channel(self, data):
        self.setData('telnet_channel', data)
        try:
            del (self.setData)['ssh_channel']
        except KeyError:
            return
        try:
            del (self.setData)['console_channel']
        except KeyError:
            return

    def setSsh_channel(self, data):
        self.setData('ssh_channel', data)
        try:
            del (self.setData)['telnet_channel']
        except KeyError:
            return
        try:
            del (self.setData)['console_channel']
        except KeyError:
            return

    def setV4_addr(self, data):
        self.setData('v4_addr', data)

    def setV6_global_addr(self, data):
        self.setData('v6_global_addr', data)

    def setV6_local_addr(self, data):
        self.setData("v6_local_addr", data)

    def setConsole_channel(self, data):
        self.setData('console_channel', data)
        try:
            del (self.setData)['ssh_channel']
        except KeyError:
            return
        try:
            del (self.setData)['telnet_channel']
        except KeyError:
            return


class sshChannel:
    """ sshChannel: This class represents all elements associated with a 
    Mu ssh object and is added to the host object
    
    -------------------------------------------------------------------------
    example JSON config data
    'ssh_channel': {'commands': [], 'password': 'admin', 'prompt': '[#$>]', 'tcp_port': 22, 
    'username': 'admin'}
    ------------------------------------------------------------------------
    
    Arguments: 
    jsonData - The JSON formated data used to populate the object
    
    Globals:
    """
    
    __channel = {'commands': [], 'password': "", 'prompt': '[#$>]',
                 'tcp_port': 22, 'username': ""}

    def __init__(self, jsonData=None):
        if jsonData == None:
            return
        self.loadFromJsonData(jsonData)

    def loadFromJsonData(self, jsonData):
        self.__channel = jsonData

    def getData(self, key):
        return (self.__channel)[key]

    def getCommands(self):
        return self.getData('commands')

    def getPassword(self):
        return self.getData('password')

    def getPrompt(self):
        return self.getData('prompt')

    def getTcp_port(self):
        return self.getData('tcp_port')

    def getUsername(self):
        return self.getData('username')

    def setData(self, key, data):
        (self.__channel)[key] = data

    def setCommands(self, data):
        self.setData('commands', data)

    def setPassword(self, data):
        self.setData('password', data)

    def setPrompt(self, data):
        self.setData('prompt', data)

    def setTcp_port(self, data):
        self.setData('tcp_port', data)

    def setUsername(self, data):
        self.setData('username', data)


class telnetChannel:

    """ telnetChannel: This class represents all elements associated with 
    a Mu telnet object and is added to the host object
    
    -------------------------------------------------------------------------
    example JSON config data
    'telnet_channel': {'commands': [],'prompt': '>', 'tcp_port': 23}
    -------------------------------------------------------------------------
    
    Arguments: 
    jsonData - The JSON formated data used to populate the object
    
    Globals:
    """
    
    __channel = {'commands': [], 'prompt': '[$#>]', 'tcp_port': 23}

    def __init__(self, jsonData=None):
        if jsonData == None:
            return
        self.loadFromJsonData(jsonData)

    def loadFromJsonData(self, jsonData):
        self.__channel = jsonData

    def getData(self, key):
        return (self.__channel)[key]

    def getCommands(self):
        return self.getData('commands')

    def getPrompt(self):
        return self.getData('prompt')

    def getTcp_port(self):
        return self.getData('tcp_port')

    def setData(self, key, data):
        (self.__channel)[key] = data

    def setCommands(self, data):
        self.setData('commands', data)

    def setPrompt(self, data):
        self.setData('prompt', data)

    def setTcp_port(self, data):
        self.setData('tcp_port', data)


class consoleChannel:

    """ consoleChannel: This class represents all elements associated with 
    a Mu console object and is added to the host object
    
    -------------------------------------------------------------------------
    example JSON config data
    'console_channel': {'baud_rate': 'BR115200', 'commands': [],'flow_control': 'None','prompt': '[$#>]','serial_port': 'consoleb'}
    -------------------------------------------------------------------------
    
    Arguments: 
    jsonData - The JSON formated data used to populate the object
    
    Globals:
    """
    
    __jsonData = {'baud_rate': 'BR115200', 'commands': [],
                  'flow_control': 'None', 'prompt': '[$#>]',
                  'serial_port': 'consoleb'}

    def __init__(self, jsonData=None):
        if jsonData == None:
            return
        self.loadFromJsonData(jsonData)

    def loadFromJsonData(self, jsonData):
        self.__jsonData = jsonData

    def __str__(self):
        return simplejson.dumps(self.__jsonData)

    def getData(self, key):
        return (self.__channel)[key]

    def getCommands(self):
        return self.getData('commands')

    def getPrompt(self):
        return self.getData('prompt')

    def getSerial_port(self):
        return self.getData('serial_port')

    def getBaud_rate(self):
        return self.getData('baud_rate')

    def getFlow_control(self):
        return self.getData('flow_control')

    def setData(self, key, data):
        (self.__channel)[key] = data

    def setCommands(self, data):
        self.setData('commands', data)

    def setPrompt(self, data):
        self.setData('prompt', data)

    def setSerial_port(self, data):
        self.setData('serial_port', data)

    def setBaud_rate(self, data):
        self.setData('baud_rate', data)

    def setFlow_control(self, data):
        self.setData('flow_control', data)


class command:
    """ command: This class represents all elements associated with a Mu 
    channel command object and is added to the telnet, ssh, or console objects
    
    -------------------------------------------------------------------------
    example JSON config data
    LIST OF COMMANDS
    {'expect_command': {'regex': 'ogin:', 'timeout': '4s'}}, {'send_command': 
    {'command': 'jbates'}}, {'expect_command': {'regex': 'word:', 'timeout': '4s'}}, 
    {'send_password_command': {'command': 'passW0rd'}}
    
    EXPECT COMMAND
    'expect_command': {'regex': 'ogin:', 'timeout': '4s'}
    SEND COMMAND
    'send_command': {'command': 'admin'}
    SLEEP COMMAND
    'sleep_command': {'delay': '2s'}
    SEND PASSWORD COMMAND
    'send_password_command': {'command': 'admin'}
    -------------------------------------------------------------------------
    
    Arguments: 
    jsonData - The JSON formated data used to populate the object
    
    Globals:
    """

    __command = {}

    def __init__(self, jsonData=None):
        if jsonData == None:
            return
        self.loadFromJsonData(jsonData)

    def loadFromJsonData(self, jsonData):
        self.__command = jsonData

    def __str__(self):
        return simplejson.dumps(self.__command)

    def getData(self, key):
        return (self.__jsonData)[key]

    def getExpect_command(self):
        return self.getData('expect_command')

    def getSleep_command(self):
        return self.getData('sleep_command')

    def getSend_command(self):
        return self.getData('send_command')

    def getSend_password_command(self):
        return self.getData('send_password_command')

    def setExpect_command(self, regex, timeout='4s'):
        command = ""
        command['expect_command'] = {'regex': regex, 'timeout': timeout}

    def setSleep_command(self, delay='2s'):
        command = ""
        command['sleep_command'] = {'delay': delay}

    def setSend_command(self, command):
        command = ""
        command['send_command'] = {'command': command}

    def setSend_password_command(self, password):
        command = ""
        command['send_password_command'] = {'command': password}


class route:
    """ route: This class represents all elements associated with a Mu 
    route object
    
    -------------------------------------------------------------------------
    example JSON config data
    'default': False, 'direct': True, 'dst': '169.254.0.0', 'dst_pfx_len': 16, 'gateway': '0.0.0.0', 
    'interface': 'eth1', 'interface_display_name': 'Aux', 'metric': 0, 'readonly': True
    -------------------------------------------------------------------------
    
    Arguments: 
    jsonData - The JSON formated data used to populate the object
    
    Globals:
    """
    
    def __init__(self, jsonData=None):
        if jsonData == None:
            return
        self.loadFromJsonData(jsonData)

    def loadFromJsonData(self, jsonData):
        self.__jsonData = jsonData

    def __str__(self):
        return simplejson.dumps(self.__jsonData)

    __jsonData = {
        'default': False,
        'direct': False,
        'dst': '0.0.0.0',
        'dst_pfx_len': 24,
        'gateway': '0.0.0.0',
        'interface': "",
        'interface_display_name': "",
        'metric': 0,
        'readonly': False,
        }

    def loadFromJsonData(self, jsonData):
        self.__jsonData = jsonData

    def getRouteData(self):
        return self.__jsonData

    def getDst(self):
        return self.getData('dst')

    def getDst_pfx_len(self):
        return self.getData('dst_pfx_len')

    def getGateway(self):
        return self.getData('gateway')

    def getInterface(self):
        return self.getData('interface')

    def getInterface_display_name(self):
        return self.getData('interface_display_name')

    def getMetric(self):
        return self.getData('metric')

    def getReadonly(self):
        return self.getData('readonly')

    def getDefault(self):
        return self.getData('default')

    def getDirect(self):
        return self.getData('direct')

    def getData(self, key):
        return (self.__jsonData)[key]

    def setDst(self, data):
        self.setData('dst', data)

    def setDst_pfx_len(self, data):
        self.setData('dst_pfx_len', data)

    def setGateway(self, data):
        self.setData('gateway', data)

    def setInterface(self, data):

        self.setData('interface', data.lower())
        self.setData('interface_display_name', data.upper())

    def setInterface_display_name(self, data):

        self.setData('interface_display_name', data)

    def setMetric(self, data):

        data = 0
        self.setData('metric', data)

    def setData(self, key, data):
        (self.__jsonData)[key] = data


